<?php
namespace app\index\logic;

use think\Db;
class AminoDifficult{
	/* 初始相关的值 */
	private $mOriginal;
	private $mSubject;
	private $mChemicalData;
	
	/* 开发过程中的临时变量  */
	private $mChains;
	private $mSubjects;
	private $mAminoDetails;
	private $mDifficultResults;
	
	/* 最后输出的结果 */
	private $mCategories=array();
	private $mDatas=array();
	private $mFinalResults;
	private $mHasError = false;
	private $mMessage = '';
    private $mHasResult = true;
	
	public function __set($name, $value){
		$this->$name = $value;
	}
	
	public function __get($name){
		return $this->$name;
	}
	
	public function init($subject){
		$subject = replace_special($subject);
		
		$this->mOriginal = $subject;
		$this->mSubject = $subject;
		$amino_standards = Db::table('amino_standard')->select();
		$amino_standard_data = array2map($amino_standards, 'single', 'full');
		
		$amino_max_length = Db::table('amino_standard')->value('max(length(full)) amino_max_length');

		$amino_side_specials = Db::name('amino_side_special')->select();
		$amino_side_special_data = array2map($amino_side_specials, 'single', 'full');

		$amino_difficults = Db::name('amino_difficult')->select();
		$amino_difficult_data = array2map($amino_difficults, 'single', 'full');
		
		$this->mChemicalData = array(
		   'standard_data'=>$amino_standard_data,
		   'side_special_data'=>$amino_side_special_data,
		   'difficult_data'=>$amino_difficult_data,
		   'amino_max_length'=>$amino_max_length
		);
	}
	
	public function analyze(){
		$subject_result = $this->checkMemo();
		$subject = $subject_result['subject'];
		$this->mSubject = $subject;
		
		$this->getChains();
		$this->analyzeSubjects();

		if($this->mHasError && $this->mHasResult===false){
			return;
		}
		
		$this->getAllDifficult();
		if($this->mHasError && $this->mHasResult===false){
			return;
		}
		
		$difficult_results = $this->mDifficultResults;
		if(count($difficult_results)==0){
			$this->setMessage('结果为空，无法预测结果');
			return;
		}
		
		$final_results = array();
		foreach($difficult_results as $chain=>$difficult_result){
			foreach($difficult_result as $chain_name=>$results){
				$categories = array();
				$datas = array();
				foreach($results as $result){
				    $show = $result['show'];
                    if($show==1){
                        array_push($categories, $result['name']);
                        array_push($datas, $result['value']);
                    }
				}
				
				$final_results[$chain.$chain_name] = array(
				       'categories'=>$categories,
				       'datas'=>$datas,
				       'subject'=>$this->buildSubject($categories),
				       'name'=>$chain.$chain_name
				);
			}
		}
		
		$this->mFinalResults = $final_results;
	}
	
	public function getResult(){
		
		return array(
		    'has_result'=>$this->mHasResult,
		   'has_error'=>$this->mHasError,
		   'message'=>$this->mMessage,
		   'original'=>$this->mOriginal,
		   'subject'=>$this->mSubject,
		   'chains'=>$this->mChains,
		   'subjects'=>$this->mSubjects,
		   'amino_details'=>$this->mAminoDetails,
		   'difficult_results'=>$this->mDifficultResults,
		   'final_results'=>$this->mFinalResults,
		   'final_size'=>count($this->mFinalResults),
		   'categories'=>$this->mCategories,
		   'datas'=>$this->mDatas
		);
	}
	
	/**
	 * 检测序列中是否包含备注信息
	 * 条件：在序列尾部的（）中，同时要检测其中的字符串是否为有效序列，若不是则为备注
	 */
	private function checkMemo(){
		$subject = $this->mSubject;
		$pattern = '/\)$/';
		$result = preg_match($pattern, $subject);
		// 尾部不存在)
		if($result==0){
			return $this->createMemoResult($subject, 'no )');
		}
		
		$stack_result = reserve_stack($subject);
		// 获取发生错误
		if($stack_result['has_error']){
			return $this->createMemoResult($subject, $stack_result['message']);
		}
		
		$start_index = $stack_result['start_index'];
		$content = $stack_result['content'];
		
		// 判断()之前是否为特殊标记符号
		$side_special_data = $this->mChemicalData['side_special_data'];
		foreach($side_special_data as $key=>$value){
			$tmp_single = $value['single'];
			$tmp_full = $value['full'];
			$tmp_flag = $value['memo_flag'];
			
			$len = strlen($tmp_single);
			$pre_index = $start_index - $len;
			if($pre_index >= 0){
				$pre_subject = substr($subject, $pre_index, $len);
				if($pre_subject==$tmp_single){
					if($tmp_flag==0){ //有特殊标记无需再继续
						return $this->createMemoResult($subject, '有特殊标记：'.$pre_subject);
					}
				}
			}
			
			if($tmp_single == $tmp_full) continue;
			
			$len = strlen($tmp_full);
			$pre_index = $start_index - $len;
			if($pre_index >= 0){
				$pre_subject = substr($subject, $pre_index, $len);
				if($pre_subject==$tmp_full){
					if($tmp_flag==0){ //有特殊标记无需再继续
					    return $this->createMemoResult($subject, '有特殊标记：'.$pre_subject);
					}
				}
			}
		}
		
		$aminoResult = $this->aminoToArray($content);
		if($aminoResult['has_error']){
			$subject = substr($subject, 0, strlen($subject) - strlen($content) - 2);
			return $this->createMemoResult($subject, $content, true);
		}
		
		return $this->createMemoResult($subject, '可转化');
	}
	/**
	 * 根据chain获取链上的序列
	 */
	private function getChains(){
    	$subject = $this->mSubject;
		$chains = array();
		$subjects = array();

		$has_chain = false;
		if(strpos($subject, 'chainA')>-1){
			$chain_result = stack($subject);
			if(isset($chain_result['hasError'])){
				return;
			}
			
			$chain_subject = $chain_result['content'];
			$subject = substr($subject, $chain_result['end_index']+1);
			
			$has_chain = true;
			$chains['A'] = $chain_subject;
			$subjects['A'] = $chain_subject;
		}
		
		if(strpos($subject, 'chainB')>-1){
			$chain_result = stack($subject);
			if(isset($chain_result['hasError'])){
				return;
			}
			
			$chain_subject = $chain_result['content'];

			$has_chain = true;
			$chains['B'] = $chain_subject;
			$subjects['B'] = $chain_subject;
		}

		if(!$has_chain){
			$chains['0'] = $subject;
			$subjects['0'] = $subject;
		}
		
        $this->mChains = $chains;
		$this->mSubjects = $subjects;
    }
    
	/**
	 * 返回memo结果
	 */
	private function createMemoResult($subject, $memo='', $hasMemo=false){
		return array(
		   'subject'=>$subject,
		   'memo'=>$memo,
		   'has_memo'=>$hasMemo
		);
	}

    /**
     * 分析所有的对象
     */
	private function analyzeSubjects(){
		$chains = $this->mChains;
		$amino_details = $this->mAminoDetails;
		$standard_data = $this->mChemicalData['standard_data'];
		$difficult_data = $this->mChemicalData['difficult_data'];

        // 序列结果
        $sequence_result = array();
        $subject_count = 0;
		foreach($chains as $chain=>$subject){
			$valid_result = $this->aminoToArray($subject);
			
			// 去除了可以忽略的特殊标记
			if($valid_result['has_error']){
				$this->removeFlag($subject);
				$valid_result = $this->aminoToArray($subject);
			}

			$subjects = array();
			// 按照其他特殊标记来计算
            /**
             * subject以多段subject计算，show=1表示需要在最后的结果中显示，show=0不显示
             */
			if($valid_result['has_error']){
				$subjects = $this->calculateSpecialFlags($subject);
			}else{
			    $subject_detail = array();
                array_push($subject_detail, array('subject'=>$subject, 'show'=>1));
			    $subjects[0] = array(
			        'detail'=>$subject_detail,
                    'full_subject'=>$subject
                );
            }
			
			$details = array();
            foreach($subjects as $index=>$tmp_subject){
                $subject_details = $tmp_subject['detail'];
                $sub_amino_details = array();
                foreach($subject_details as $subject_detail){
                    $current_subject = $subject_detail['subject'];
                    $show = $subject_detail['show'];
                    $valid_result = $this->aminoToArray($current_subject);
                    if($valid_result['has_error']){
                        $this->setMessage($valid_result['message']);
                        $this->mHasResult = false;
                        return;
                    }else{
                        $sub_amino_detail = $valid_result['amino_detail'];
                        if(count($sub_amino_detail)==0){
                            $this->setMessage('序列为空，无需预测');
                            $this->mHasResult = false;
                            return;
                        }

                        foreach($sub_amino_detail as $amino){
                            array_push($sub_amino_details, array('amino'=>$amino, 'show'=>$show));
                        }
                    }
                }
                $subject_count++;
                $amino_detail = $sub_amino_details;
                $amino_detail_count = count($amino_detail);

                if($amino_detail_count==0){
                    $this->setMessage('序列为空，无需预测');
                    $this->mHasResult = false;
                    return;
                }
                $last_amino = $amino_detail[$amino_detail_count-1];
                $amino_standard_data = $standard_data[$last_amino['amino']];
                $amino_difficult_data = $difficult_data[$last_amino['amino']];

                if($amino_standard_data['flag']==3 && $amino_difficult_data['contain']==1){
                    $this->setMessage('请确认是否可以采用固相进行合成');
                    $this->mHasResult = false;
                    return;
                }

                if($amino_difficult_data['contain']==0){
                    $amino_detail = array_slice($amino_detail, 0 , $amino_detail_count-1);
                }
                if(count($amino_detail)<5){
                    array_push($sequence_result, array(
                        'has_error'=>true,
                        'message'=>'序列短，无需预测合成难度',
                        'subject'=>$tmp_subject,
                        'index'=>$index
                    ));
                    continue;
                }
                $details[$index] = $amino_detail;
                $amino_details[$chain] = $details;
            }
        }

		$sequence_result_count = count($sequence_result);

		if($sequence_result_count>0){
           if($subject_count==$sequence_result_count){
               $this->setMessage($sequence_result[0]['message']);
               $this->mHasResult = false;
           }else if($sequence_result_count<$subject_count){

               $has_index0 = 0;
               $message = '';
               foreach ($sequence_result as $result){
                 $message = $message  .$result['subject'].','.$result['message'].'<br>';
                   if($result['index']==0){
                       $has_index0 = 1;
                   }
               }
               if($has_index0==1){
                   $this->setMessage('有'.$subject_count.'条主侧链，但：'.$message);
               }

           }
        }
		$this->mAminoDetails = $amino_details;
	}
	/**
	 * 去除需要忽略的特殊标记
	 */
	private function removeFlag(&$subject){
		$side_special_data = $this->mChemicalData['side_special_data'];
		foreach($side_special_data as $amino=>$side_special){
			if($side_special['flag']!=0) continue;

			$location = strpos(strtolower($subject), strtolower($amino.'('));
			if($location===-1 || $location===false) continue;
			
			if($location==0){
				$result = stack($subject);
				$start_index = $result['start_index'];
				$end_index = $result['end_index'];
				$content = $result['content'];
				$subject = $content . substr($subject, $end_index+1);
			}else{
				//若不在第一个，则需要把后面拿出来比较
				$pre = substr($subject, 0, $location);
				
				$cyclo_subject = substr($subject, $location);
				$cyclo_result = stack($cyclo_subject);
				$cyclo_content = $cyclo_result['content'];
				$cyclo_end_index = $cyclo_result['end_index'];
				$subject = $pre . $cyclo_content. substr($cyclo_subject, $cyclo_end_index+1);
			}
			
			$valid_result = $this->aminoToArray($subject);
			if($valid_result['has_error']){
				$this->removeFlag($subject);
			}
		}
	}
	
	private function calculateSpecialFlags($subject){
		$side_special_data = $this->mChemicalData['side_special_data'];
		$flag_data = null;
		$special_result = array(
		   'start_index'=>-1,
		   'end_index'=>0,
		   'content'=>'',
		   'has_flag'=>false,
		   'flag_name'=>'',
		   'flag_data'=>$flag_data
		);
		
		foreach($side_special_data as $key=>$side_special){
			$single = $side_special['single'];
			$full = $side_special['full'];
			$result_number = preg_match('/'.strtolower($single).'\(.+\)/', strtolower($subject));

			if($result_number>0){
				$single_result = stack($subject);
				$start_index = strpos(strtolower($subject), strtolower($single).'(');
				$old_start_index = $special_result['start_index'];
                // 取最先出现的特殊flag
				if($old_start_index==-1 || $start_index <= $old_start_index){
					$special_result['start_index'] = $start_index;
					$special_result['end_index'] = $single_result['end_index'];
					$special_result['content'] = $single_result['content'];
				    $special_result['has_flag'] = true;
				    $special_result['flag_name'] = $single;
					$special_result['flag_data'] = $side_special;
				}
			}
			
			if($single==$full){ // 若单多字母一样，只校验一遍
				continue;
			}
			
			$result_number = preg_match('/'.strtolower($full).'\(.+\)/', strtolower($subject));
			
			if($result_number>0){
				$full_result = stack($subject);
				$start_index = strpos(strtolower($subject), strtolower($full).'('); //必须得有()
				
				$old_start_index = $special_result['start_index'];
				if($old_start_index==-1 || $start_index <= $old_start_index){
					$special_result['start_index'] = $start_index;
					$special_result['end_index'] = $full_result['end_index'];
					$special_result['content'] = $full_result['content'];
				    $special_result['has_flag'] = true;
				    $special_result['flag_name'] = $full;
					$special_result['flag_data'] = $side_special;
				}
			}
		}
		
		$start_index = $special_result['start_index'];
		$end_index = $special_result['end_index'];
		if($start_index==-1){
			$message = '序列存在无法识别字符:'.$subject;
			return array(
			 'has_error'=>true,
			 'message'=>$message
			);
		}
		
		$flag_data = $special_result['flag_data'];
		// 记录特殊标记
		$flag_name = $flag_data['single'];
		$subject1 = substr($subject, 0, $start_index);
		$subject2 = $special_result['content'];
		$subject3 = substr($subject, $end_index+1);

		$subjects = array();
        $term = $flag_data['term'];
        if($term==1){
            $subject_detail1 = array();
            $subject_detail2 = array();
            $sequence1 = $subject1 . $flag_name ;
            $sequence2 = $subject2 . '-' . $flag_name ;

            array_push($subject_detail2, array('subject'=>$subject2, 'show'=>1));
            if(strlen($subject3)>0) {
                if(strpos($subject3, '-')==-1){
                    $sequence1 = $sequence1 . '-' . $subject3;
                    $sequence2 = $sequence2 . '-' . $subject3;

                    array_push($subject_detail2, array('subject'=>$flag_name.'-'.$subject3, 'show'=>0));
                }else{
                    $sequence1 = $sequence1  . $subject3;
                    $sequence2 = $sequence2  . $subject3;
                    array_push($subject_detail2, array('subject'=>$flag_name.$subject3, 'show'=>0));
                }
            }
            array_push($subject_detail1, array('subject'=>$sequence1, 'show'=>1));
            $sequence1_subject1 = array(
                'detail'=>$subject_detail1,
                'full_subject'=>$sequence1
            );
            $sequence2_subject2 = array(
                'detail'=>$subject_detail2,
                'full_subject'=>$sequence2
            );
            array_push($subjects, $sequence1_subject1);
            array_push($subjects, $sequence2_subject2);
        }else if($term==-1){
            $sequence1 = $subject1 . $flag_name ;
            if(strlen($subject3)>0){
                if(strpos($subject3, '-')==-1){
                    $sequence1 = $sequence1 . '-' . $subject3;
                }else{
                    $sequence1 = $sequence1  . $subject3;
                }
            }
            $subject_detail1 = array();
            array_push($subject_detail1, array('subject'=>$sequence1, 'show'=>1));
            $sequence_subject1 = array(
                'detail'=>$subject_detail1,
                'full_subject'=>$sequence1
            );
            array_push($subjects, $sequence_subject1);
        }
		return $subjects;
	}
	/**
	 * 获取所有序列的合成难度
	 */
	private function getAllDifficult(){
		$amino_details = $this->mAminoDetails;
		if(count($amino_details)==0){
			$this->setMessage('氨基酸序列为空，无需计算');
			return;
		}
		
		$difficult_data = $this->mChemicalData['difficult_data'];
		
		$difficult_results = array();
		foreach($amino_details as $chain=>$amino_detail){
			$chain = $chain=='0' ? '' : 'chain'.$chain;
			$difficult_results[$chain] = array();
			foreach($amino_detail as $index=>$details){
				$name = $index==0 ? '主链' : '侧链'.$index;
				$results = array();
				$this->calculateDifficult($results, $details, $difficult_data);
				$difficult_results[$chain][$name] = $results;
			}
		}
		$this->mDifficultResults = $difficult_results;
	}
	
	/**
	 * 计算单个序列的合成难度
	 */
	private function calculateDifficult(&$results, $details, $difficult_data){
	    $tmp_details = $details;
        $details = array();
        // 首先去除不计算在氨基酸个数中的氨基酸
        foreach($tmp_details as $tmp_detail){
            $amino = $tmp_detail['amino'];
            $show = $tmp_detail['show'];
            $tmp_difficult_data = $difficult_data[$amino];
            if(isset($tmp_difficult_data)){
                $contain = $tmp_difficult_data['contain'];
                if($contain==1){
                    array_push($details, $tmp_detail);
                }
            }
        }

		$detail_count = count($details);
        // 默认为倒数第5个位置开始计算
        $start_index = $detail_count - 5;
        for($index=$detail_count-1; $index>=0; $index--){
            $tmp_detail = $details[$index];
            $amino = $tmp_detail['amino'];
            if(strpos(strtoupper($amino), 'MAP')>-1){ // 氨基酸中包含MAP
               if( ($detail_count-$index) < 5 ){
                   $start_index = $index - 1;
                   break;
               }
            }
        }

        $max_correct2_result = $this->getCorrect2($details, $difficult_data);
        $max_correct2 = $max_correct2_result['max_correct2'];
        $correct2_location = $max_correct2_result['correct2_location'];

        $next_amino_length = $detail_count - $start_index;

        $pre_flag1 = 0;
        $flag1 = 0;
        $flag2 = 0;
        $flag12 = 0;

        /**
         * 计算start_index到尾部的所有氨基酸的特性
         */
        for($index=$detail_count-1; $index>$start_index; $index--){
            $detail = $details[$index];
            $amino = $detail['amino'];
            $current_difficult_data = $difficult_data[$amino];
            if(is_null($current_difficult_data)) break;
            $flag = $current_difficult_data['flag'];
            if($flag==1){
                $pre_flag1 = 1;
                $flag1++;
                $flag2=0;
                $flag12++;
            }else if($flag==2){
                $flag1=0;
                $flag2++;
                $flag12++;
            }else{
                if($pre_flag1==1){
                    $flag1 ++;
                }else{
                    $flag1=0;
                }
                $pre_flag1 = 0;
                $flag2=0;
                $flag12=0;
            }
        }

		for($index=$start_index; $index>=0; $index--){
            $detail = $details[$index];
            $amino = $detail['amino'];
            $show = $detail['show'];
            $current_difficult_data = $difficult_data[$amino];
            if(is_null($current_difficult_data)) break;

			$sub_details = array_slice($details, $index, $next_amino_length);
			$difficult_sum = 0;

            $max_correct2_result = $this->getCorrect2($sub_details, $difficult_data, $max_correct2, $correct2_location, $index);
            $max_correct2 = $max_correct2_result['max_correct2'];
            $correct2_location = $max_correct2_result['correct2_location'];
			foreach($sub_details as $sub_detail){
				$difficult_sum += $difficult_data[$sub_detail['amino']]['difficult'];
			}

            $next_detail = $details[$index+1];
            $next_amino = $next_detail['amino'];
            $next_amino_correct1 = $difficult_data[$next_amino]['correct_1'];
            $difficult_value = $difficult_sum / $next_amino_length + $next_amino_correct1 ;

            $flag = $current_difficult_data['flag'];
            $pre_flag1 = 0;
            if(isset($next_detail)){
                $pre_flag1 = $difficult_data[$next_detail['amino']]['flag'];
            }
            if($flag==1){
                $flag1++;
                $flag2=0;
                $flag12++;
            }else if($flag==2){
                if($flag12>=5 && $pre_flag1==1){
                    $flag1++;
                }else{
                    $flag1=0;
                }
                $flag2++;
                $flag12++;
            }else{
                if($pre_flag1==1){
                    $flag1++;
                    $flag12++;
                }else{
                    $flag1=0;
                    $flag12=0;
                }
                $flag2=0;

            }

            if($flag12>=5){
                $flag1_value = 0;
                $flag2_value = 0;
                if($flag1>=5){
                    if($flag==1){
                        $flag1_value = ($flag1 - 5+1) * 0.1;
                    }else{
                        if($pre_flag1==1 && $flag==2){
                            $flag1_value = ($flag1 - 5+1) * 0.1;
                        }
                    }
                    $flag1_value = ($flag1_value>=0.5) ? 0.5 : $flag1_value;
                }else{
                    if($pre_flag1==1 && $flag==2){
                        $flag1_value = ($flag12 - 5+1) * 0.1;
                        $flag1_value = ($flag1_value>=0.5) ? 0.5 : $flag1_value;
                    }
                    if($flag==1){
                        $flag2_value = ($flag12-8+1)*0.05;
                        $flag2_value = ($flag2_value>=0.3) ? 0.3 : $flag2_value;
                    }
                }


                if($flag==2 || $flag==1){
                    $tmp_flag2 = $flag12;
                    if($tmp_flag2>=8){
                        $flag2_value = ($flag12-8+1)*0.05;
                        $flag2_value = ($flag2_value>=0.3) ? 0.3 : $flag2_value;
                    }
                }

                $final_plus_value = ($flag1_value > $flag2_value) ? $flag1_value : $flag2_value;
                $difficult_value += $final_plus_value;
                //echo "index=$index flag12=$flag12 flag=$flag pre_flag1=$pre_flag1 flag1=$flag1 flag1_value=$flag1_value flag2=$flag2 flag2_value=$flag2_value final_value=$final_plus_value\r\n";
            }
            if($index < $correct2_location){
                $difficult_value += $max_correct2;
            }

			array_push($results, $this->pushResultValue($amino, $difficult_value, $show));
            $next_amino_length = ($next_amino_length==5) ? 5 : ($next_amino_length+1);
		}
		//反向result
		$results = array_reverse($results);
	}

    /**
     * 获取序列中非0的correct2, 以倒叙获取
     * @param $details array() 序列
     * @param $difficult_data array() 合成难度数据
     * @param null $other_correct2 另外的correct2，若非0，则可拿出比较
     * @param $start_location int 起始location，计算最终的location
     * @return array()
     */
	private function getCorrect2($details, $difficult_data, $other_correct2=null, $other_location=-1, $start_location=0){
	    $details_count = count($details);
        $max_correct2 = 0;
        $correct2_location = -1;
        for($index=$details_count-1; $index>=0; $index--){
            $correct2 = $difficult_data[$details[$index]['amino']]['correct_2'];
            if($correct2!=0){
                $max_correct2 = $correct2;
                $correct2_location = $index + $start_location;
                break;
            }
        }
        if(!is_null($other_correct2) && $other_correct2 > $max_correct2){
            $max_correct2 =  $other_correct2;
        }
        //echo "other_location=$other_location correct2_location=$correct2_location\r\n";

        if($other_location!=-1 && $correct2_location==-1){
            $correct2_location = $other_location;
        }
        return array(
            'max_correct2'=>$max_correct2,
            'correct2_location'=>$correct2_location
        );
    }
	/**
	 * 将amino字符串序列序列转换为数组
	 * @param $checkAmino @mixed 需要检查的序列
	 */
	private function aminoToArray($checkAmino){
		$standard_data = $this->mChemicalData['standard_data'];
		$amino_max_length = $this->mChemicalData['amino_max_length'];
		
		$result = array();
		$amino_length = strlen($checkAmino);
		$index = 0;
	    
		if(is_null($standard_data) || empty($standard_data)){
			return array(
			  'has_error'=>true,
			  'message'=>'可校验的标准数据为空，无法校验'
			);
		}
		
		while($index < $amino_length){
			//当前校验的字符串长度
			$current_amino_length = strlen($checkAmino); 
			
			// 按照标准最长长度去计算子序列
			$sub_length = ($amino_max_length < $current_amino_length) ? $amino_max_length : $current_amino_length;
			$sub_amino_result = $this->getSubAmino($standard_data, $amino_max_length, $checkAmino);
			
			if(is_null($sub_amino_result)){
				return array(
				   'has_error'=>true,
				   'message'=>'校验错误,未获取正确的子序列结果'
				);
			}
			
			if($sub_amino_result['has_error']){
				return $sub_amino_result;
			}
			
			$sub_amino = $sub_amino_result['sub_amino'];

			if(array_key_exists($sub_amino, $standard_data)){
			     array_push($result, $sub_amino);
				 $sub_amino_length = $sub_amino_result['real_length'];
				 $index = $index + $sub_amino_length;
				 $checkAmino = substr($checkAmino, $sub_amino_length);
			}
		}
		$valid_result = array(
		   'has_error'=>false,
		   'message'=>'校验正确',
		   'amino_detail'=>$result
		);
		return $valid_result;
	}
	
	/**
	 * 获取正确的子序列
	 * 根据data文件中给出的最长序列进行匹配，从长到短直到匹配，若最后未能找到的，则提示错误
	 */
	private function getSubAmino($standardData, $aminoMaxLength, $checkAmino){
		$length = strlen($checkAmino);
		$sub_length = ($aminoMaxLength > $length) ? $length : $aminoMaxLength;
	    $real_length = $sub_length;
		
		$tmp_check_amino = $checkAmino;
		
		if(strpos($tmp_check_amino, '-')===0 && strlen($tmp_check_amino)>0){
			if(array_key_exists($tmp_check_amino, $standardData)){
				return array(
				   'sub_amino'=>$tmp_check_amino,
				   'real_length'=>$real_length,
				   'has_error'=>false,
				   'message'=>'正确匹配'
				);
			}
			// 若以-开头直接去判断，若有则返回，若无，则去除-
			$tmp_check_amino = substr($tmp_check_amino, 1);
			$sub_length--;
		}
		
		$sub_amino = substr($tmp_check_amino, 0, $sub_length);
		
		if(array_key_exists($sub_amino, $standardData)){
			return array(
			   'sub_amino'=>$sub_amino,
			   'real_length'=>$real_length,
			   'has_error'=>false,
			   'message'=>'正确匹配'
			);
		}else{
			if($aminoMaxLength<=0){
				return array(
				   'has_error'=>true,
				   'message'=>"此段序列：$checkAmino  存在无法识别字符"
				);
			}
			$amino_max_length = $aminoMaxLength - 1;
			return $this->getSubAmino($standardData, $amino_max_length, $checkAmino);
		}
	}
	
	private function pushResultValue($name, $value, $show=1){
		return array(
		    'name'=>$name,
            'value'=>$value,
            'show'=>$show
		);
	}
	
	private function setMessage($message, $hasError=true){
		$this->mMessage = $message;
		$this->mHasError = $hasError;
	}
	
	private function buildSubject($categories){
		$subject = '';
		if(count($categories)>0){
			$pre = '';
			foreach($categories as $index=>$category){
			    if($index==0){
			        $subject = $subject . $category;
                    $pre = $category;
                }else{
                    $old_category = $category;
                    if(strlen($pre)>1){
                        $category = '-' . $category;
                    }else{
                        if(strlen($category)>1){
                            $category = '-' . $category;
                        }
                    }
                    $subject = $subject . $category;
                    $pre = $old_category;
                }
		    }
		}
		return $subject;
	}
}
